/*
 * tlog.h
 *
 *  Created on: 2011-08-16
 *      Author: Baron Wang
 */

#ifndef TLOG_H_
#define TLOG_H_

#ifdef __cplusplus
extern "C" {
#endif

/*
 * The tlog is a light-weighted logger that commonly used in trans and tsock
 *
 * tlog provides a much more readable log format that is good for debug, it
 * also can be used to connect to the common log function as syslog format:
 *         void (*logger)(int prio, const char* format, ...);
 *
 * And the tlog can be seemlessly work with syslog, just init log_opt as:
 *         { NULL, def_level, syslog} with <syslog.h> included.
 *
 * If want only syslog with no extension, use _USE_SYSLOG. (re-compile)
 *
 * The loglevel is the same with syslog, 0 is the highest and 7 is for debug.
 * suggest using level 1(_ASS) ~ 6(_RTM).
 *
 */

typedef void (*logger)(int prio, const char* format, ...);

typedef struct{
    const char*         logfile;        /* the log file                     */
    int                 def_lvl;        /* default log level, suggest 1 ~ 6 */
    logger              log;            /* the logger if have, or use tlog  */
}log_opt;

/* It is supposed and suggested to check the entrance parameters only */
#define CHECKNULL(_p, _opt)                             \
    if(NULL == _p){                                     \
        LOG(_ASS, "A NULL pointer encoutered.");        \
        _opt;                                           \
     }

#ifdef _NO_LOG
#define LOG(...)            ;
#define DUMP(...)           ;
#define LOG_ANYWAY(...)     ;
#define GETLOGLEVEL         1
#define SETLOGLEVEL(_x)     ;
#define INIT_LOGGER(_x)     0
#define IS_LOG_INIT         1
#define CHKLOGLVL(_lv)      if(0)
#define FINI_LOGGER         ;

#else /* _NO_LOG */

#ifdef _USE_SYSLOG
#include <syslog.h>
#define LOG                 syslog
#define DUMP(...)           ;
#define LOG_ANYWAY(...)     ;
#define GETLOGLEVEL         7
#define SETLOGLEVEL(_x)     ;
#define INIT_LOGGER(_x)     0
#define IS_LOG_INIT         1
#define CHKLOGLVL(_lv)      if(1)
#define FINI_LOGGER         ;

#define _DBG                L_DBG
#define _RTM                L_RTM
#define _CHK                L_CHK
#define _WRN                L_WRN
#define _ERR                L_ERR
#define _CRI                L_CRI
#define _ASS                L_ASS
#define _SYS                L_SYS

#else

/* use internal log which has a rich content and can be work with syslog */
#define LOG                 log_msg
#define DUMP                dump_msg
#define LOG_ANYWAY          log_anyway
#define GETLOGLEVEL         log_get_lv()
#define SETLOGLEVEL         log_set_lv
#define INIT_LOGGER         init_logger
#define IS_LOG_INIT         is_init()
#define FINI_LOGGER         fini_logger()

#define CHKLOGLVL(_lv)      if(GETLOGLEVEL >= _lv)

#define _DBG                L_DBG, __FILE__, __LINE__, __FUNCTION__
#define _RTM                L_RTM, __FILE__, __LINE__, __FUNCTION__
#define _CHK                L_CHK, __FILE__, __LINE__, __FUNCTION__
#define _WRN                L_WRN, __FILE__, __LINE__, __FUNCTION__
#define _ERR                L_ERR, __FILE__, __LINE__, __FUNCTION__
#define _CRI                L_CRI, __FILE__, __LINE__, __FUNCTION__
#define _ASS                L_ASS, __FILE__, __LINE__, __FUNCTION__
#define _SYS                L_SYS, __FILE__, __LINE__, __FUNCTION__

#endif /* _USE_SYSLOG */
#endif /* _NO_LOG */

/*
 * The internal log implementation, user should ignore of this function by
 * just use the macro before.
 */

enum{
    L_SYS = 0,              /* LOG_EMERG, NOT USED                      */
    L_ASS = 1,              /* LOG_ALERT, ASSERT for system error       */
    L_CRI = 2,              /* LOG_CRIT, CRI CASE, highest log level    */
    L_ERR = 3,              /* LOG_ERR, ERROR CASE, high log level      */
    L_WRN = 4,              /* LOG_WARNING, error but continue          */
    L_CHK = 5,              /* LOG_NOTICE, CHECK STATUS, medium level   */
    L_RTM = 6,              /* LOG_INFO, RUN TIME, lowest log level     */
    L_DBG = 7,              /* LOG_DEBUG, NOT USED                      */
};

int  log_get_lv(void);
void log_set_lv(int lv);

int  init_logger(log_opt *opt);
void fini_logger(void);
int  is_init(void);

void log_msg(int lv, const char* file, int line, const char* func,
         const char *format, ...);
void dump_msg(int lv, const char* file, int line, const char* func,
         const char* raw, int len);
void log_anyway(const char *format, ...);

#ifdef __cplusplus
}
#endif

#endif /* TLOG_H_ */
